package com.chengcang.api.common.exception;

import com.chengcang.api.common.annotation.RateLimit;
import com.chengcang.api.modules.login.service.RateLimitService;
import com.chengcang.common.utils.Result;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;

@Component
public class RateLimitInterceptor extends HandlerInterceptorAdapter {
    private RateLimitService rateLimitService;

    public void setRateLimitService(RateLimitService rateLimitService) {
        this.rateLimitService = rateLimitService;
    }

    private ObjectMapper objectMapper;

    public void setObjectMapper(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 判断请求是否属于方法的请求
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            // 获取方法中的注解,看是否有该注解
            RateLimit rateLimit = handlerMethod.getMethodAnnotation(RateLimit.class);
            if (rateLimit == null) {
                return true;
            }
            // 请求IP地址
            String ip = request.getRemoteAddr();
            String[] split = ip.split(":");
            String s = StringUtils.join(split, ".");
            // 请求url路径
            String uri = request.getRequestURI();
            if (!rateLimitService.limit(s, uri, rateLimit)) {
                response.setContentType("application/json;charset=UTF-8");
                response.getWriter().write(objectMapper.writeValueAsString(new Result().error(rateLimit.msg())));
                response.setStatus(HttpStatus.OK.value());
                return false;
            }

            return rateLimitService.limit(s, uri, rateLimit);
        }

        return true;

    }
}
